home *** CD-ROM | disk | FTP | other *** search
/ C/C++ Users Group Library 1996 July / C-C++ Users Group Library July 1996.iso / vol_100 / 108_01 / concord.c < prev    next >
Text File  |  1985-11-13  |  8KB  |  242 lines

  1.  
  2. /**********************************************************
  3.  ***                            ***
  4.  ***    Copyright (c) 1981 by David M. Fogg        ***
  5.  ***                            ***
  6.  ***        2632 N.E. Fremont            ***
  7.  ***        Portland, OR 97212            ***
  8.  ***                            ***
  9.  ***        (503) 288-3502{HM} || 223-8033{WK}        ***
  10.  ***                            ***
  11.  ***    Permission is herewith granted for non-     ***
  12.  ***    commercial distribution through the BDS C    ***
  13.  ***    User's Group; any and all forms of commercial   ***
  14.  ***    redistribution are strenuously unwished-for.    ***
  15.  ***                            ***
  16.  **********************************************************/
  17.  
  18. /* --->  CONCORD  <--- : generate Concordance raw outfile */
  19.  
  20. /* 6 Nov 80: convert from KWIC */
  21.  
  22. /*
  23.    Programs generates index lines from IFILE to IFILE.UNC
  24.     for sorting to generate a concordance.
  25.  
  26.    Words in skip list or < minlen chars long are skipped;
  27.     skip list is originally: A, AN, THE, AND, OR.
  28.  
  29.    Chars are output in uppercase.
  30.  
  31.    -A option: if on, defines word begin as 1st ALPHANUMERIC char,
  32.     rather than first non-whitespace (NB: this affects word length).
  33.    -C option: defeats auto-chain -> MSORT -> MERGE.
  34.       NB: auto-chain turns on Ignore case option in MSORT & MERGE.
  35.       MSORT will kill IFILE.UNC; MERGE will kill IFILE.A+...
  36.       CONCORD calculates and passes on average line length to
  37.         MSORT for most efficient use of sort buffer.
  38.    -L# option: reset minimum word length to '#'; default is 2.
  39.    -Nc option: char 'c' at the beginning of a word causes that word to
  40.       be skipped (NB: -A option turned off).
  41.    -Oc option: char 'c' MUST be at the beginning of a word for that
  42.       word to be used (NB: overrides -A & -N options).
  43.  
  44.    Additional arguments in input command line are taken as
  45.     words to add to the skip list.
  46.  
  47.    If no ODRIV is specified, all files will be created on the input
  48.       file drive; if ODRIV is specified, then the files will ping-pong
  49.       between input file drive & ODRIVE. For example:
  50.  
  51.      CONCORD INDEX.RAW B:         (A:INDEX.RAW --> B:INDEX.UNC)
  52.      MSORT B:INDEX.UNC -L10   (B:INDEX.UNC --> A:INDEX.A+...)
  53.      MERGE INDEX B:INDEX.CON -I  (A:INDEX.A+... --> B:INDEX.CON)
  54.  
  55. */
  56.  
  57. #include <std.h>
  58.  
  59. #define MAXLEN    130    /* max line length */
  60. #define MSKIPS    30    /* max # of words in skiplist */
  61. #define DEFMIN    2    /* default min word length */
  62.  
  63.  
  64. main (ac, av)
  65. int ac;
  66. char *av[];
  67. {
  68.    char ilin[MAXLEN];    /* input line buffer */
  69.    char tlin[MAXLEN];    /* test line buffer {UCASE ilin} */
  70.    int llen;        /* length of current line */
  71.    int curwd;        /* pos of 1st char of curr wd */
  72.    int wdlen;        /* length of curr wd */
  73.    int i;
  74.    BOOL alfon;        /* whether to start words @ 1st alfanum */
  75.    BOOL only;        /* ONLY-words-starting-w/a-char flag */
  76.    BOOL not;        /* NOT    ditto above */
  77.    char onlych;     /* ONLY start char allowed */
  78.    char notch;        /* NOT allowed 2b start char */
  79.    int nxarg;
  80.    char ibuf[BUFSIZ];    /* infile buffer */
  81.    char obuf[BUFSIZ];    /* outfile buffer */
  82.    int nskips;        /* # of words in default skip list */
  83.    char *skips[MSKIPS]; /* pointers to skip list words */
  84.    BOOL gosort;     /* to chain or not to chain */
  85.    char inam[15];    /* input file name */
  86.    char onam[15];    /* output file name */
  87.    int ppos;        /* period position in onam */
  88.    int argn;        /* curr arg# in options code */
  89.    char *arg;        /* curr arg in options code */
  90.    unsigned tc, tl;    /* tot chars, lins in ifile so far */
  91.    int lino;        /* lines output so far */
  92.    char avlen[20];    /* str vrsn of avg line len of ofile */
  93.    int minlen;        /* min word length */
  94.    char punct[20];    /* punctuation characters */
  95.    char test[2];    /* test 1-char string for punctuation chk */
  96.    int newd;        /* hold val of curwd */
  97.  
  98. /*
  99.     ---> INITIALIZATION <---
  100. */
  101.    gosort = YES; alfon = only = not = NO;
  102.    test[1] = notch = onlych = NULL;
  103.    nskips = 5;
  104.    nxarg = 2;
  105.    lino = tl = tc = 0;
  106.    strcpy(avlen, "-L");
  107.    minlen = DEFMIN;
  108.    punct[0] = 0x22 /*"*/; punct[1] = NULL; strcat(punct, "!)}]>\';:?.,");
  109.  
  110.    skips[0] ="AN"; skips[1] ="THE"; skips[2] ="AND"; skips[3] ="OR";
  111.    skips[4] ="A";
  112.  
  113.    if (ac < 2) {
  114.       puts("usage: concord IFILE [ODRIV] [-A -C -Nc -Oc] [words]\n");
  115.       puts("IFILE: name of input file\n");
  116.       puts("ODRIV: (e.g., B:) where to put IFILE.UNC\n");
  117.       puts("   -A: start words @ 1st ALFANUMERIC, 'stead of 1st non-blank\n");
  118.       puts("   -C: don't CHAIN to msort & merge\n");
  119.       puts("  -L#: set minimum word length to # (default=2)\n");
  120.       puts("  -Nc: NOT use words that start with <c>\n");
  121.       puts("  -Oc: ONLY use words that start with <c>\n");
  122.       puts("words: added to skip list (an the and or)\n");
  123.       exit ();
  124.    }
  125.  
  126.    strcpy(inam, av[1]);
  127.    if (fopen(inam, ibuf) == ERROR)
  128.       errxit("Input file error");
  129.  
  130.    if (ac > 2 && *(av[2]+1) == ':') {      /* set up outfile name */
  131.       strcpy(onam, av[2]);
  132.       if (strlen(onam) > 2) errxit("Bad output drive field");
  133.       strcat(onam, inam + instr(inam, ":"));
  134.       ++nxarg;
  135.    }
  136.    else
  137.       strcpy(onam, inam);
  138.    if (ppos = instr(onam, "."))
  139.       strcpy(onam + ppos, "UNC");
  140.    else
  141.       strcat(onam, ".UNC");
  142.  
  143.    if (fcreat(onam, obuf) == ERROR)
  144.       errxit("Output file error");
  145.  
  146.  
  147.    /*
  148.       ---> GET OPTIONS <---
  149.    */
  150.    for (argn = 1; argn < ac; ++argn) {
  151.       arg = av[argn];
  152.       if (*arg == '-')
  153.      switch (arg[1]) {
  154.         case 'C': gosort = NO; ++nxarg;
  155.               break;
  156.         case 'A': alfon = YES; ++nxarg;
  157.               break;
  158.         case 'L': minlen = atoi(arg + 2);
  159.               if (minlen < 1)
  160.             errxit("Bad minimum word length value");
  161.               ++nxarg;
  162.               break;
  163.         case 'N': not = YES; notch = arg[2];
  164.               alfon = only = NO; onlych = NULL;
  165.               ++nxarg;
  166.               break;
  167.         case 'O': only = YES; onlych = arg[2];
  168.               alfon = not = NO; notch = NULL;
  169.               ++nxarg;
  170.               break;
  171.         default :
  172.            errxit("Bad option value");
  173.      }
  174.    }
  175.  
  176.    while (nxarg < ac)             /* get xtra skip wds (if any) */
  177.       skips[nskips++] = av[nxarg++];
  178.  
  179. /*
  180.     ---> MAIN LOOP <---
  181. */
  182.    while (fgets(ilin, ibuf) != 0) {
  183.       llen = strlen(ilin); ilin[--llen] = '\0';
  184.       ++tl;
  185.       for (i = 0; i < llen; ++i)
  186.      tlin[i] = toupper(ilin[i]);
  187.       tlin[llen] = NULL;
  188.       curwd = 0;
  189.       while (curwd < llen) {
  190.      while (isspace(tlin[curwd]) && ++curwd < llen)
  191.         ;
  192.      while (alfon
  193.         && !isalpha(tlin[curwd]) && !isdigit(tlin[curwd])
  194.         && ++curwd < llen)
  195.         ;
  196.      wdlen = 1;
  197.      while (!isspace(tlin[curwd+wdlen]) && curwd + wdlen < llen)
  198.         ++wdlen;
  199.      newd = curwd + wdlen;
  200.      do {
  201.         test[0] = tlin[curwd + --wdlen];
  202.      } while (instr(punct, test));
  203.      ++wdlen;
  204.      if ((only && ilin[curwd] == onlych)
  205.      || (!only && wdlen >= minlen
  206.        && noskip(tlin+curwd, wdlen, skips, nskips)
  207.        && (!not || ilin[curwd] != notch))) {
  208.         tc += wdlen; ++lino;
  209.         tlin[curwd+wdlen] = NULL;
  210.         fprintf(obuf, "%s %5d\n", tlin+curwd+only, tl);
  211.      }
  212.      curwd = ++newd;
  213.       } /* while (curwd... */
  214.    } /* while (fgets... */
  215.    fclose(ibuf); oclose(obuf);
  216.  
  217.    if (gosort) {               /* ---> msort? */
  218.       inam[instr(inam, ":")] = NULL;
  219.       sprintf(avlen+2, "%d", tc / lino + 7);
  220.       printf("\n--> msort %s %s %s\n", onam, inam, avlen);
  221.       execl("msort", onam, inam, avlen, 0);
  222.    }
  223. }
  224.  
  225.  
  226. BOOL noskip (wd, len, skips, nskips)    /* see if wd in skips */
  227. char *wd;
  228. int len;
  229. char *skips[];
  230. int nskips;
  231. {
  232.    int i;
  233.    char twd[MAXLEN];
  234.  
  235.    strcpy(twd, wd); twd[len] = '\0';
  236.  
  237.    for (i = 0; i < nskips; ++i)
  238.       if (strcmp(skips[i], twd) == 0)
  239.      return(NO);
  240.    return(YES);
  241. }
  242.